package org.puremvc.as3.multicore.patterns.facade
{
	import org.puremvc.as3.multicore.core.Controller;
	import org.puremvc.as3.multicore.core.Messaging;
	import org.puremvc.as3.multicore.core.MessagingConnector;
	import org.puremvc.as3.multicore.core.Model;
	import org.puremvc.as3.multicore.core.ReView;
	import org.puremvc.as3.multicore.interfaces.IFacade;
	import org.puremvc.as3.multicore.interfaces.IMessage;
	import org.puremvc.as3.multicore.interfaces.IMessaging;
	import org.puremvc.as3.multicore.interfaces.ISystemControll;
	
	/**
	 * 
	 */
	public class ReFacade extends Facade implements IMessaging, ISystemControll
	{
		public function ReFacade(key:String)
		{
			super(key);
		}
		
		/**
		 * Initialize the Multiton <code>Facade</code> instance.
		 * 
		 * It has to be reimplemented here, because the order of the
		 * initialization process have to be reordered.
		 * 
		 * In the original <code>Facade</code>, the 
		 * <code>Controller</code> references the <code>View</code>, before
		 * <code>initializeView</code> has been called. 
		 * 
		 * <P>
		 * Called automatically by the constructor. Override in your
		 * subclass to do any subclass specific initializations. Be
		 * sure to call <code>super.initializeFacade()</code>, though.</P>
		 */
		override protected function initializeFacade(  ):void {
			initializeView();
			initializeModel();
			initializeController();
			
			/*
			* Custom Initialization
			*/
			initializeMessaging();
		}
		
		/**
		 * Facade Multiton Factory method
		 * 
		 * @return the Multiton instance of the Facade
		 */
		public static function getInstance( key:String ):IFacade {
			if (instanceMap[ key ] == null ) 
				instanceMap[ key ] = new ReFacade( key );
			return instanceMap[ key ];
		}
		
		/**
		 * Initialize the <code>View</code>.
		 * 
		 * <P>
		 * Called by the <code>initializeFacade</code> method.
		 * Override this method in your subclass of <code>Facade</code> 
		 * if one or both of the following are true:
		 * <UL>
		 * <LI> You wish to initialize a different <code>IView</code>.</LI>
		 * <LI> You have <code>Observers</code> to register with the <code>View</code></LI>
		 * </UL>
		 * If you don't want to initialize a different <code>IView</code>, 
		 * call <code>super.initializeView()</code> at the beginning of your
		 * method, then register <code>IMediator</code> instances.
		 * <P>
		 * Note: This method is <i>rarely</i> overridden; in practice you are more
		 * likely to use a <code>Command</code> to create and register <code>Mediator</code>s
		 * with the <code>View</code>, since <code>IMediator</code> instances will need to send 
		 * <code>INotification</code>s and thus will likely want to fetch a reference 
		 * to the <code>Facade</code> during their construction. 
		 * </P>
		 */
		override protected function initializeView( ):void {
			if ( view != null ) 
				return;
			view = ReView.getInstance( multitonKey );
		}
		
		protected function initializeMessaging():void {
			if ( messaging != null) {
				return;
			}
			messaging = new Messaging( multitonKey );
		}
		
		
		/**
		 * Remove a Core.
		 * <P>
		 * Remove the Model, View, Controller and Facade 
		 * instances for the given key.</P>
		 * 
		 * @param multitonKey of the Core to remove
		 */
		public static function removeCore( key:String ) : void
		{
			if (instanceMap[ key ] == null) return;
			Model.removeModel( key ); 
			ReView.removeView( key );
			Controller.removeController( key );
			delete instanceMap[ key ];
		}
		
		/**
		 * 
		 * @param messageName
		 * @param commandClassRef
		 * 
		 */
		protected function registerMessageCommand(messageName:String, commandClassRef:Class):void {
			messaging.registerMessageCommand(messageName, commandClassRef);
		}
		
		/*
		* IMessaging
		*/
		
		/**
		 * Sends a message to the world outside.
		 */
		public function send(message:IMessage):void {
			messaging.send(message);
		}
		
		/**
		 * receives a message from the world outside.
		 */
		public function receive(message:IMessage):void {
			messaging.receive(message);
		}
		
		/**
		 * sets the message bus
		 */
		public function messagingConnector(callback:MessagingConnector):void {
			messaging.connector(callback);
		}
		
		/*
		* ISystemControll
		*/
		
		public function startup(view:Object):void {
			
		}
		
		public function shutdown(callback:Function):void {
			ReFacade.removeCore(this.multitonKey);
		}

		protected var messaging:Messaging;
		
	}
}